﻿namespace Jsl.FxCop
{
    using System;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using Microsoft.FxCop.Sdk;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class TestRuleTestHelper
    {
        #region Properties
        public int Public_instance_Property { get; set; }

        private int Private_instance_Property { get; set; }

        public static int Public_static_Property { get; set; }

        private static int Private_static_property { get; set; }

        [TestMethod]
        public void Works_on_properties_using_expressions()
        {
            ListBuilder<Expression<Func<int>>, string>
                .AddItem(() => this.Public_instance_Property, "Public_instance_Property")
                .AddItem(() => this.Private_instance_Property, "Private_instance_Property")
                .AddItem(() => TestRuleTestHelper.Public_static_Property, "Public_static_Property")
                .AddItem(() => TestRuleTestHelper.Private_static_property, "Private_static_property")
                .Run((expression, propertyName) =>
                    {
                        var rule = new TargetRule();
                        rule.RunRule(expression);

                        AssertEx.That(() => rule.MembersChecked.Count == 1);
                        AssertEx.That(() => rule.MembersChecked[0].Name.Name == propertyName);
                    });
        }

        [TestMethod]
        public void Works_on_properties_using_hard_coded_names()
        {
            new string[]
            {
                "Public_instance_Property",
                "Private_instance_Property",
                "Public_static_Property",
                "Private_static_property"
            }.Run(propertyName =>
                {
                    var rule = new TargetRule();
                    rule.RunPropertyRule(typeof(TestRuleTestHelper), propertyName);

                    AssertEx.That(() => rule.MembersChecked.Count == 1);
                    AssertEx.That(() => rule.MembersChecked[0].Name.Name == propertyName);
                });
        }
        #endregion Properties

        #region Fields
        public int public_instance_field;
        public static int public_static_field;
        private int private_instance_field = 0;
        private static int private_static_field = 0;

        [TestMethod]
        public void Works_on_fields()
        {
            ListBuilder<Expression<Func<int>>, string>
                .AddItem(() => this.public_instance_field, "public_instance_field")
                .AddItem(() => this.private_instance_field, "private_instance_field")
                .AddItem(() => TestRuleTestHelper.public_static_field, "public_static_field")
                .AddItem(() => TestRuleTestHelper.private_static_field, "private_static_field")
                .Run((expression, fieldName) =>
                    {
                        var rule = new TargetRule();
                        rule.RunRule(expression);

                        AssertEx.That(() => rule.MembersChecked.Count == 1);
                        AssertEx.That(() => rule.MembersChecked[0].Name.Name == fieldName);
                    });
        }
        #endregion Fields

        ////#region Methods
        ////public int Public_instance_function() { return 0; }
        ////public static int Public_static_function() { return 0; }
        ////private int Private_instance_function() { return 0; }
        ////private static int Private_static_function() { return 0; }

        ////[TestMethod]
        ////public void Works_on_functions()
        ////{
        ////    ListBuilder
        ////        .AddItem<Expression<Func<int>>, string>(() => this.Public_instance_function(), "Public_instance_function")
        ////        .AddItem(() => this.Private_instance_function(), "Private_instance_function")
        ////        .AddItem(() => TestRuleTestHelper.Public_static_function(), "Public_static_function")
        ////        .AddItem(() => TestRuleTestHelper.Private_static_function(), "Private_static_function")
        ////        .Run((expression, methodName) =>
        ////            {
        ////                var rule = new TargetRule();
        ////                rule.RunRule(expression);

        ////                AssertEx.That(() => rule.MembersChecked.Count == 1);
        ////                AssertEx.That(() => rule.MembersChecked[0].Name.Name == methodName);
        ////            });
        ////}
        ////#endregion Methods

        ////[TestMethod]
        ////public void Returns_problems_found_in_check()
        ////{
        ////    new TargetRule() { .ProblemsToReturn = new ProblemCollection() }
        ////        .RunRule(
        ////}
    }

    internal class TargetRule : BaseIntrospectionRule
    {
        public IList<Member> MembersChecked = new List<Member>();
        public ProblemCollection ProblemsToReturn = null;

        #region Constructors
        public TargetRule()
            : base("TargetRule", "Jsl.FxCop.Rules", typeof(TargetRule).Assembly)
        {
        }
        #endregion Constructors

        #region Public Methods
        public override ProblemCollection Check(Member member)
        {
            this.MembersChecked.Add(member);

            return this.ProblemsToReturn;
        }
        #endregion Public Methods
    }
}